﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace 桌面视频录制
{
    [Serializable]
    public class DrawParallelogram : DrawRectangle
    {
        protected int hypotenuse;
        protected float includeAngle1;
        protected float includeAngle2;
        protected double slope1, slope2;
        public DrawParallelogram(Point leftUpPoint)
            : base(leftUpPoint) 
        {
            this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
            this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
            this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
            this.slope1 = 1.0 * (leftUpPoint.Y - leftDownPoint.Y) / (leftUpPoint.X - leftDownPoint.X);
            this.slope2 = 1.0 * (leftUpPoint.Y - rightUpPoint.Y) / (leftUpPoint.X - rightUpPoint.X);
        }
        public override void MouseMove(System.Windows.Forms.MouseEventArgs e)
        {
            base.MouseMove(e);
            this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
            this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
            this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
            this.slope1 = 1.0 * (leftUpPoint.Y - leftDownPoint.Y) / (leftUpPoint.X - leftDownPoint.X);
            this.slope2 = 1.0 * (leftUpPoint.Y - rightUpPoint.Y) / (leftUpPoint.X - rightUpPoint.X);
        }
        public override void Draw(Graphics g)
        {
            Pen pen = new Pen(this.PenColor);
            pen.Width = this.PenWidth;
            g.DrawPolygon(pen, new Point[] { leftUpPoint, rightUpPoint, rightDownPoint, leftDownPoint });;
            pen.Dispose();
        }
        public override bool JudgeIsSelected(System.Windows.Forms.MouseEventArgs e)
        {
            GraphicsPath path = new GraphicsPath();
            path.AddPolygon(new Point[] { leftUpPoint, rightUpPoint, rightDownPoint, leftDownPoint });
            Region region = new Region(path);
            if (region.IsVisible(e.Location))
            {
                path.Dispose();
                region.Dispose();
                return true;
            }
            else
            {
                path.Dispose();
                region.Dispose();
                return false;
            }
        }
        public override void ChangeSize(System.Windows.Forms.MouseEventArgs e)
        {
            if (selectedIndex == 0)
            {
                leftUpPoint = e.Location;
                rightUpPoint = GetPoint(e.Location, leftDownPoint, rightDownPoint);
                this.width = GetDistance(leftUpPoint, rightUpPoint);
                this.height = GetDistance(leftUpPoint, leftDownPoint);
                this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
                this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                this.slope1 = 1.0 * (leftUpPoint.Y - leftDownPoint.Y) / (leftUpPoint.X - leftDownPoint.X);
                this.slope2 = 1.0 * (leftUpPoint.Y - rightUpPoint.Y) / (leftUpPoint.X - rightUpPoint.X);
            }
            else if (selectedIndex == 1)
            {
                leftDownPoint = e.Location;
                rightDownPoint = GetPoint(e.Location, leftUpPoint, rightUpPoint);
                this.width = GetDistance(leftUpPoint, rightUpPoint);
                this.height = GetDistance(leftUpPoint, leftDownPoint);
                this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
                this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                this.slope1 = 1.0 * (leftUpPoint.Y - leftDownPoint.Y) / (leftUpPoint.X - leftDownPoint.X);
                this.slope2 = 1.0 * (leftUpPoint.Y - rightUpPoint.Y) / (leftUpPoint.X - rightUpPoint.X);
            }
            else if (selectedIndex == 2)
            {
                angle = (float)(Math.Atan2(e.Y - leftUpPoint.Y, e.X - leftUpPoint.X));//直线斜率对应的角度 
                rightUpPoint = GetRotatePoint(width, leftUpPoint, angle);
                leftDownPoint = GetRotatePoint(height, leftUpPoint, (float)(angle + includeAngle2));
                rightDownPoint = GetRotatePoint(hypotenuse, leftUpPoint, angle + includeAngle1);
                //计算旋转后左侧边的斜率
                if (leftUpPoint.X != leftDownPoint.X && leftUpPoint.X != rightUpPoint.X)
                {
                    this.slope1 = 1.0 * (leftUpPoint.Y - leftDownPoint.Y) / (leftUpPoint.X - leftDownPoint.X);
                    this.slope2 = 1.0 * (leftUpPoint.Y - rightUpPoint.Y) / (leftUpPoint.X - rightUpPoint.X);
                }
            }
            else if (selectedIndex == 3)
            {  
                rightDownPoint = e.Location;
                leftDownPoint = GetPoint(e.Location, rightUpPoint, leftUpPoint);
                this.width = GetDistance(leftUpPoint, rightUpPoint);
                this.height = GetDistance(leftUpPoint, leftDownPoint);
                this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
                this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                this.slope1 = 1.0 * (leftUpPoint.Y - leftDownPoint.Y) / (leftUpPoint.X - leftDownPoint.X);
                this.slope2 = 1.0 * (leftUpPoint.Y - rightUpPoint.Y) / (leftUpPoint.X - rightUpPoint.X);
            }
            else if (selectedIndex == 4)
            {
                if (Double.IsInfinity(slope1) == false && Double.IsInfinity(slope2) == false)
                {
                    leftUpPoint = GetChangePoint(e.Location, leftDownPoint, slope2, slope1);
                    rightUpPoint = GetChangePoint(e.Location, rightDownPoint, slope2, slope1);
                    this.width = GetDistance(leftUpPoint, rightUpPoint);
                    this.height = GetDistance(leftUpPoint, leftDownPoint);
                    this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
                    this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                    this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                }
            }
            else if (selectedIndex == 5)
            {
                if (Double.IsInfinity(slope1) == false && Double.IsInfinity(slope2) == false)
                {
                    leftUpPoint = GetChangePoint(e.Location, rightUpPoint, slope1, slope2);
                    leftDownPoint = GetChangePoint(e.Location, rightDownPoint, slope1, slope2);
                    this.width = GetDistance(leftUpPoint, rightUpPoint);
                    this.height = GetDistance(leftUpPoint, leftDownPoint);
                    this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
                    this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                    this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                }
            }
            else if (selectedIndex == 6)
            {
                if (Double.IsInfinity(slope1) == false && Double.IsInfinity(slope2) == false)
                {
                    leftDownPoint = GetChangePoint(e.Location, leftUpPoint, slope2, slope1);
                    rightDownPoint = GetChangePoint(e.Location, rightUpPoint, slope2, slope1);
                    this.width = GetDistance(leftUpPoint, rightUpPoint);
                    this.height = GetDistance(leftUpPoint, leftDownPoint);
                    this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
                    this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                    this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                }
            }
            else if (selectedIndex == 7)
            {
                if (Double.IsInfinity(slope1) == false && Double.IsInfinity(slope2) == false)
                {
                    rightUpPoint = GetChangePoint(e.Location, leftUpPoint, slope1, slope2);
                    rightDownPoint = GetChangePoint(e.Location, leftDownPoint, slope1, slope2);
                    this.width = GetDistance(leftUpPoint, rightUpPoint);
                    this.height = GetDistance(leftUpPoint, leftDownPoint);
                    this.hypotenuse = GetDistance(rightDownPoint, leftUpPoint);
                    this.includeAngle1 = GetIncludeAngle(leftUpPoint, rightDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                    this.includeAngle2 = GetIncludeAngle(leftUpPoint, leftDownPoint, rightUpPoint);//矩形对角线与横边的夹角
                }
            }
        }

        private Point GetChangePoint(Point point, Point p1, double k1, double k2)
        {
            int x = (int)((p1.Y - point.Y + k1 * point.X - k2 * p1.X) / (k1 - k2));
            int y = (int)(k1 * (x - point.X) + point.Y);
            return new Point(x, y);
        }
 
        private int GetDistance(Point p1, Point p2)
        {
            return (int)(Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2)));
        }

        private float GetIncludeAngle(Point leftUpPoint, Point rightDownPoint, Point rightUpPoint)
        {
            //余弦定理：cos∠BAC＝(AB²+AC²-BC²)/(2*AB*AC)
            double ab2 = Math.Pow(leftUpPoint.X - rightUpPoint.X, 2) + Math.Pow(leftUpPoint.Y - rightUpPoint.Y, 2);
            double ac2 = Math.Pow(leftUpPoint.X - rightDownPoint.X, 2) + Math.Pow(leftUpPoint.Y - rightDownPoint.Y, 2);
            double bc2 = Math.Pow(rightUpPoint.X - rightDownPoint.X, 2) + Math.Pow(rightUpPoint.Y - rightDownPoint.Y, 2);
            return (float)(Math.Acos(1.0 * (ab2 + ac2 - bc2) / (2 * Math.Sqrt(ab2) * Math.Sqrt(ac2))));
        }

        private Point GetPoint(Point p, Point p1, Point p2)
        {
            Point point = new Point();
            point.X = p.X + p2.X - p1.X;
            point.Y = p.Y + p2.Y - p1.Y;
            return point;
        }
        public override string ToString()
        {
            string printMsg = "[菱形(" + this.leftUpPoint.X + "," + this.leftUpPoint.Y + ")]->[ID:" + this.Id + "]";
            return printMsg;
        }
        public override string GetDrawObjectMsg()
        {
            string drawObjectMsg = "菱形->起始位置(" + this.leftUpPoint.X + "," + this.leftUpPoint.Y + "),宽高(" + this.width + "," + this.height + "),偏移角度:" + ((int)(angle * 180 / Math.PI)) + "°";
            return drawObjectMsg;
        }
    }
}
